package ai;

import game.Game;

public class AlphaBetaImproved extends MinmaxImproved {
	
	//Set the maximum depth of recursion for the algorithm
	private final static int MAX_DEPTH = 8;
	
	public AlphaBetaImproved(Game game, byte side) {
		super(game, side);
	}
	
	protected int getZet()
	{
		//Copy a new playing field to the ai-array.
		copyPlayingField( this.game.getPlayingField() );
		
		
		//Set the counter to zero
		this.counter = 0;
		
		int reply = chooseMove( this.side, MINIMUM_VALUE, MAXIMUM_VALUE, 0 );
		
		System.out.println("AlphaBetaImproved counter: "+this.counter);

		
		if(reply <= MINIMUM_VALUE)
		{
			System.out.println("AlphaBetaImproved giving up, bestmove: "+this.bestmove);
		}
		
		
		return bestmove;
	}
	
	//Recursive function to determine the optimal move
	private int chooseMove(byte side, int alpha, int beta, int depth)
	{
		byte opponent;
		int value;
		int bestmove = 0;
		int reply;
		
		//Base case
		int basecase = evaluateField(this.side);
		if (depth >= MAX_DEPTH || basecase == LOSE_VALUE || basecase == WIN_VALUE || isDraw())
		{
			return basecase;
		}
		
		//Increment the counter
		this.counter++;
		
		if (side == this.side)
		{
			opponent = this.opponent;
			value = alpha;
		}
		else
		{
			opponent = this.side;
			value = beta;
		}
		
		
		//Main loop
		Outer:
		for (int i = 0; i < Game.XSIZE; i++)
		{
			if ( ! this.columnIsFull(i) )
			{
				placeToken(i, side);
				reply = chooseMove(opponent, alpha, beta, depth + 1);
				removeToken(i);
				
				//DEBUG:
				//if (depth == 0)
				//{
				//	System.out.println("Column: "+i+" has Strength: "+reply);
				//}
				
				//Update the return value if we've found a better posibility
				if (side == this.side && reply > value ||
						side == this.opponent && reply < value)
				{
					value = reply;
					bestmove = i;
					
					if( side == this.side)
						alpha = reply;
					else
						beta = reply;
					
					//Checking if it's a refutation, if so then skip node
					if (alpha >= beta)
						break Outer; // Refutation
				}
				
			}
		}
		
		//Only update the bestmove at the highest level (depth 0)
		if (depth == 0)
		{
			this.bestmove = bestmove;
		}
		return value;
	}
	
}
